package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.oms.entity.OrderEntity;
import com.atguigu.gmall.order.interceptor.LoginInterceptor;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.order.vo.OrderConfirmVo;
import com.atguigu.gmall.order.vo.OrderSubmitVo;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/")
public class OrderController {
    @Autowired
    OrderService orderService;
    //处理异步提交订单的请求
    @ResponseBody
    @PostMapping("submit")
    public ResponseVo<String> submit(@RequestBody OrderSubmitVo submitVo){
        OrderEntity orderEntity = orderService.createOrder(submitVo);
        return ResponseVo.ok(orderEntity.getOrderSn());
    }
    //跳转到结算页的接口
    @GetMapping("confirm")
    public String confirm(Model model){
        //使用userId：  使用拦截器传递userId给后续的业务使用
        OrderConfirmVo confirmVo = orderService.confirm();
        model.addAttribute("confirmVo" , confirmVo);
        return "trade";
    }
    @Autowired
    RedissonClient redissonClient;
    /*
    用户秒杀接口
     */
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    RabbitTemplate rabbitTemplate;
    @ResponseBody
    @GetMapping("seckill/{skuId}")
    public String secondKill(@PathVariable("skuId") Long skuId){//秒杀商品id
        Long userId = LoginInterceptor.getUserInfo().getUserId();
        //获取库存
        String s = redisTemplate.opsForValue().get("sec:stock:" + skuId);
        if(StringUtils.isEmpty(s)){
            return "秒杀结束!!!";
        }
        //保证原子性的方案1：分布式锁：保证秒杀业务的原子性
        //方案2： LUA脚本： 查询库存如果有则-1返回成功否则返回失败
        RLock fairLock = redissonClient.getFairLock("sec:kill:" + skuId);//每个秒杀商品对应一个分布式锁
        try {
            fairLock.lock();
            //通过分布式信号量保存 skuId商品的数量
            RSemaphore semaphore = redissonClient.getSemaphore("sec:kill:sem:" + skuId);
            if(!semaphore.isExists()){
                //初始化信号量的资源数量
                semaphore.trySetPermits(Integer.parseInt(s));
            }
            semaphore.tryAcquire();//尝试获取信号量资源

            //秒杀成功：发送消息到mq 消息队列
            Map map = new HashMap();
            map.put("userId" , userId);
            map.put("skuId",skuId);
            map.put("count" , 1);

            //创建闭锁：避免用户直接查询为创建完毕的订单
            RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("sec:kill:cdl:" + userId);//只能锁自己的信息
            countDownLatch.trySetCount(1);//初始化倒计数值
//            semaphore.release();//不能释放信号量资源
            //mq消息队列可以接受消息  创建订单持久化
            rabbitTemplate.convertAndSend("sec_exchange","sec.kill.success" ,map );//订单创建成功后获取userId的闭锁，然后调用
            //countDownLatch.countDown()释放闭锁的阻塞
            return "秒杀成功";
        } finally {
            fairLock.unlock();
        }

    }


    /*
    用户秒杀后查询秒杀订单接口
     */
    @GetMapping("getSecKillOrder/{skuId}")
    public String getSecKillOrder(@PathVariable("skuId") Long skuId) throws InterruptedException {
        Long userId = LoginInterceptor.getUserInfo().getUserId();
        //有可能异步创建订单还未成功
        //使用分布式闭锁：倒计数器，如果倒计数为0  使用await阻塞的方法才会继续执行
        RCountDownLatch countDownLatch = redissonClient.getCountDownLatch("sec:kill:cdl:" + userId);
        countDownLatch.await();
        //查询订单  跳转到秒杀订单页面的业务代码
        return "order";
    }
}
